package com.powerbank.ordercenter.mq.transaction;

import com.powerbank.common.event.order.OrderStatusChangedEvent;
import com.powerbank.ordercenter.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

/**
 * 订单事务消息监听器
 * 确保订单状态更新和消息发送的一致性
 */
@Slf4j
@Component
@RocketMQTransactionListener(rocketMQTemplateBeanName = "rocketMQTemplate")
public class OrderTransactionListener implements RocketMQLocalTransactionListener {

    @Autowired
    private OrderService orderService;

    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        try {
            log.info("执行订单本地事务: arg={}", arg);
            
            // arg参数通常是订单ID
            Long orderId = (Long) arg;
            
            // 执行本地事务：更新订单状态
            boolean success = orderService.updateOrderStatusInTransaction(orderId);
            
            if (success) {
                log.info("订单本地事务执行成功: orderId={}", orderId);
                return RocketMQLocalTransactionState.COMMIT;
            } else {
                log.warn("订单本地事务执行失败: orderId={}", orderId);
                return RocketMQLocalTransactionState.ROLLBACK;
            }
            
        } catch (Exception e) {
            log.error("订单本地事务执行异常: arg={}", arg, e);
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        try {
            // 从消息中获取订单ID
            Long orderId = extractOrderIdFromMessage(msg);
            log.info("检查订单本地事务状态: orderId={}", orderId);
            
            if (orderId == null) {
                log.warn("无法获取订单ID，回滚事务");
                return RocketMQLocalTransactionState.ROLLBACK;
            }
            
            // 查询订单状态
            String orderStatus = orderService.getOrderStatus(orderId);
            
            if (orderStatus == null) {
                log.warn("订单不存在: orderId={}", orderId);
                return RocketMQLocalTransactionState.ROLLBACK;
            }
            
            // 根据订单状态决定事务状态
            switch (orderStatus) {
                case "COMPLETED":
                case "RETURNED":
                case "CANCELLED":
                    log.info("订单已完成状态变更，提交事务: orderId={}, status={}", orderId, orderStatus);
                    return RocketMQLocalTransactionState.COMMIT;
                case "FAILED":
                    log.info("订单状态变更失败，回滚事务: orderId={}, status={}", orderId, orderStatus);
                    return RocketMQLocalTransactionState.ROLLBACK;
                default:
                    log.info("订单状态变更进行中，等待下次检查: orderId={}, status={}", orderId, orderStatus);
                    return RocketMQLocalTransactionState.UNKNOWN;
            }
            
        } catch (Exception e) {
            log.error("检查订单本地事务状态异常", e);
            return RocketMQLocalTransactionState.UNKNOWN;
        }
    }

    /**
     * 从消息中提取订单ID
     */
    private Long extractOrderIdFromMessage(Message msg) {
        try {
            // 尝试从消息头获取
            Object orderId = msg.getHeaders().get("orderId");
            if (orderId != null) {
                return Long.valueOf(orderId.toString());
            }
            
            // 如果消息体是OrderStatusChangedEvent，从中获取
            Object payload = msg.getPayload();
            if (payload instanceof OrderStatusChangedEvent) {
                OrderStatusChangedEvent event = (OrderStatusChangedEvent) payload;
                return event.getOrderId();
            }
            
            log.warn("无法从消息中提取订单ID: headers={}, payload={}", 
                    msg.getHeaders(), msg.getPayload());
            return null;
            
        } catch (Exception e) {
            log.error("提取订单ID失败", e);
            return null;
        }
    }
}